home *** CD-ROM | disk | FTP | other *** search
/ Apple Developer Connection Student Program / ADC Tools Sampler CD Disk 3 1999.iso / Metrowerks CodeWarrior / Java Support / Java_Source / IFC_112 / netscape / application / TextField.java < prev    next >
Encoding:
Text File  |  1999-05-28  |  74.9 KB  |  2,450 lines  |  [TEXT/CWIE]

  1. // TextField.java
  2. // By Ned Etcode
  3. // Copyright 1995, 1996, 1997 Netscape Communications Corp. All rights reserved.
  4.  
  5. package netscape.application;
  6.  
  7. import netscape.util.*;
  8.  
  9.  
  10. /** View subclass that displays and, optionally, lets the user edit a mono-
  11.   * font string.
  12.   * TextFields have owners that are notified of important events within the
  13.   * TextField, such as the completion of an editing session. They also have
  14.   * filters that can filter or process each key event received by the
  15.   * TextField. On certain events, such as receiving a tab key, the TextField
  16.   * can send a command to a Target interested in reacting to that event.
  17.   * @note 1.0 added drawableCharacter for password purpose.
  18.   * @note 1.0 added isScrollable and all draws to dirtRects
  19.   * @note 1.0 major changes
  20.   * @note 1.0 Added FormElement interface for browser needs
  21.   * @note 1.1 The Caps Lock key will generate a keystroke under JDK 1.1.x
  22.   * @note 1.1 Handles tab/backtab wiring properly 
  23.   * @note 1.1.1 TextField supports extended key events if available
  24.   */
  25. public class TextField extends View implements ExtendedTarget, FormElement {
  26.     TextFieldOwner      _owner;
  27.     TextFilter          _filter;
  28.     Target              _tabTarget, _backtabTarget, _contentsChangedTarget,
  29.                         _commitTarget;
  30.     Vector              _keyVector;
  31.     Border              border = BezelBorder.loweredBezel();
  32.     Font                _font;
  33.     Color               _textColor, _backgroundColor, _selectionColor,
  34.                         _caretColor;
  35.     String              _tabCommand, _backtabCommand, _contentsChangedCommand,
  36.                         _commitCommand;
  37.     FastStringBuffer    _contents, _oldContents;
  38.     Timer               blinkTimer;
  39.     char                _drawableCharacter;
  40.     int                 _selectionAnchorChar = -1, _selectionEndChar = -1,
  41.                         _justification, _scrollOffset, _fontHeight,
  42.                         _initialAnchorChar = -1,_clickCount;
  43.     boolean             _editing, _caretShowing, _canBlink, _editable,
  44.                         _selectable, _mouseDragging, _shadowed,
  45.                         _textChanged = false, _canWrap, transparent = false,
  46.                         wantsAutoscrollEvents = false, isScrollable = true,
  47.                         hasFocus = false, _ignoreWillBecomeSelected;
  48.  
  49.     /** Constant to indicate that any character can be displayed
  50.      *  @see setDrawableCharacter()
  51.      */
  52.     public static char  ANY_CHARACTER = (char)-1;
  53.  
  54.     /** Command to select the TextField's entire contents. */
  55.     final public static String  SELECT_TEXT = "selectText";
  56.     final static String         BLINK_CARET = "blinkCaret";
  57.  
  58.     final static String OWNER_KEY = "owner",
  59.                         FILTER_KEY = "filter",
  60.                         TABREC_KEY = "tabTarget",
  61.                         BACKTABREC_KEY = "backtabTarget",
  62.                         CONTENTSCHANGEDREC_KEY = "contentsChangedTarget",
  63.                         COMMITREC_KEY = "commitTarget",
  64.                         BORDER_KEY = "border",
  65.                         FONT_KEY = "font",
  66.                         TEXTC_KEY = "textColor",
  67.                         BACKGROUNDC_KEY = "backgroundColor",
  68.                         SELECTIONC_KEY = "selectionColor",
  69.                         CARETC_KEY = "caretColor",
  70.                         TABCOM_KEY = "tabCommand",
  71.                         BACKTABCOM_KEY = "backtabCommand",
  72.                         CONTENTSCHANGEDCOM_KEY = "contentsChangedCommand",
  73.                         COMMITCOM_KEY = "commitCommand",
  74.                         CONTENTS_KEY = "contents",
  75.                         SELECTIONANCH_KEY = "selectionAnchorChar",
  76.                         SELECTIONEND_KEY = "selectionEndChar",
  77.                         JUSTIFICATION_KEY = "justification",
  78.                         SCROLLOFFSET_KEY = "scrollOffset",
  79.                         EDITABLE_KEY = "editable",
  80.                         SELECTABLE_KEY = "selectable",
  81.                         SHADOWED_KEY = "shadowed",
  82.                         CANWRAP_KEY = "canWrap",
  83.                         AUTOSCROLLEVENT_KEY = "wantsAutoscrollEvents",
  84.                         TRANSPARENT_KEY = "transparent",
  85.                         DRAWABLE_CHAR_KEY = "drawableCharacter",
  86.                         DRAWABLE_CHAR_STRING_KEY = "drawable char",
  87.                         SCROLLABLE_KEY = "isScrollable";
  88.  
  89.  
  90.  
  91.     /* constructors */
  92.  
  93.     /** Constructs a TextField with origin (<b>0</b>, <b>0</b>) and zero
  94.       * width and height.
  95.       */
  96.     public TextField() {
  97.         this(0, 0, 0, 0);
  98.     }
  99.  
  100.     /** Constructs a TextField with bounds <B>rect</B>.
  101.       */
  102.     public TextField(Rect rect) {
  103.         this(rect.x, rect.y, rect.width, rect.height);
  104.     }
  105.  
  106.     /** Constructs a TextField with
  107.       * bounds (<B>x</B>, <B>y</B>, <B>width</B>, <B>height</B>).
  108.       */
  109.     public TextField(int x, int y, int width, int height) {
  110.         super(x, y, width, height);
  111.  
  112.         _keyVector = new Vector();
  113.  
  114.         _contents = new FastStringBuffer();
  115.         _drawableCharacter = ANY_CHARACTER;
  116.         _textColor = Color.black;
  117.         _backgroundColor = Color.white;
  118.         _selectionColor = Color.lightGray;
  119.         _caretColor = Color.black;
  120.  
  121.         setEditable(true);
  122.         setFont(Font.defaultFont());
  123.     }
  124.  
  125.     /** Creates a new TextField that is suitable for use as a "label": it has
  126.       * no Border, is transparent, and is not editable or selectable. The
  127.       * label displays <b>string</b> using <b>font</b>.
  128.       * This method is obsolete. Use the <b>Label</b> class instead.
  129.       * @see Label
  130.       * @deprecated
  131.       */
  132.     public static TextField createLabel(String string, Font font) {
  133.         FontMetrics metrics = font.fontMetrics();
  134.         int width = metrics.stringWidth(string),
  135.             height = metrics.stringHeight();
  136.         TextField label = new TextField(0, 0, width, height);
  137.  
  138.         label.setBorder(null);
  139.         label.setStringValue(string);
  140.         label.setFont(font);
  141.         label.setTransparent(true);
  142.         label.setEditable(false);
  143.         label.setSelectable(false);
  144.         return label;
  145.     }
  146.  
  147.     /** Creates a new TextField that is suitable for use as a "label": it has
  148.       * no Border, is transparent, and is not editable or selectable. The label
  149.       * displays <b>string</b> using the default font.
  150.       */
  151.     public static TextField createLabel(String string) {
  152.         return createLabel(string, Font.defaultFont());
  153.     }
  154.  
  155.     private static int parseInt(String s) {
  156.         try {
  157.             return Integer.parseInt(s);
  158.         } catch (NumberFormatException e) {
  159.             return 0;
  160.         }
  161.     }
  162.  
  163. /* dimensional attributes */
  164.  
  165.    /** Returns the distance between the interior edge of the TextField's
  166.     * left border and the first character. By default, this method returns
  167.     * the left margin of the TextField's Border.
  168.     */
  169.     public int leftIndent() {
  170.         int leftIndent;
  171.  
  172.         // ALERT!
  173.         leftIndent = border.leftMargin();
  174.         if (leftIndent > 2)
  175.             leftIndent = 2;
  176.  
  177.         return leftIndent;
  178.     }
  179.  
  180.     /** Returns the distance between the interior edge of the TextField's right
  181.       * border and the last character. By default, returns the right margin
  182.       * plus 1 of the TextField's Border.
  183.       */
  184.     public int rightIndent() {
  185.         int rightIndent;
  186.  
  187.         // ALERT!
  188.         rightIndent = border.rightMargin() + 1;
  189.         if (rightIndent > 3)
  190.             rightIndent = 3;
  191.  
  192.         return rightIndent;
  193.     }
  194.  
  195.     /** Returns the distance between the interior edge of the TextField's left
  196.       * border and the first character, and the right border and the last
  197.       * character. Equivalent to the code:
  198.       * <pre>
  199.       *     leftIndent() + rightIndent()
  200.       * </pre>
  201.       */
  202.     private int widthIndent() {
  203.         return leftIndent() + rightIndent();
  204.     }
  205.  
  206.     /** Returns the TextField's minimum size.
  207.      */
  208.     public Size minSize() {
  209.         Vector  stringVector;
  210.         Rect    interiorRect;
  211.         Size    theSize;
  212.  
  213.         if (_minSize != null) {
  214.             return new Size(_minSize);
  215.         }
  216.  
  217.         theSize = _font.fontMetrics().stringSize(drawableString());
  218.         interiorRect = interiorRect();
  219.  
  220.         /* if text can wrap and width is fixed, compute min height */
  221.         if ((horizResizeInstruction() != WIDTH_CAN_CHANGE) && _canWrap &&
  222.             !isEditable() && theSize.width > interiorRect.width) {
  223.             stringVector = stringVectorForContents(interiorRect.width);
  224.             theSize.sizeTo(interiorRect.width,
  225.                            theSize.height * stringVector.count());
  226.         }
  227.         Rect.returnRect(interiorRect);
  228.  
  229.         theSize.sizeBy(border.widthMargin() + widthIndent(),
  230.                        border.heightMargin());
  231.  
  232.         return theSize;
  233.     }
  234.  
  235.  
  236.  
  237. /* appearance attributes */
  238.  
  239.  
  240.     /** Set the character used to display the contents.
  241.       * the default is <B>ANY_CHARACTER</B>.
  242.       *
  243.       */
  244.     public void setDrawableCharacter(char aChar) {
  245.         _drawableCharacter = aChar;
  246.         _scrollOffset = 0;
  247.         _computeScrollOffset();
  248.         setDirty(true);
  249.     }
  250.  
  251.     /** Return the character used to display the contents **/
  252.     public char drawableCharacter() {
  253.         return _drawableCharacter;
  254.     }
  255.  
  256.     /** Sets the TextField's Font and redraws the TextField.  The default Font
  257.       * is Font.defaultFont().
  258.       * @see Font#defaultFont
  259.       */
  260.     public void setFont(Font aFont) {
  261.         Size    stringSize;
  262.  
  263.         if (aFont == null) {
  264.             _font = Font.defaultFont();
  265.         } else {
  266.             _font = aFont;
  267.         }
  268.  
  269.         stringSize = _font.fontMetrics().stringSize(null);
  270.         _fontHeight = stringSize.height;
  271.  
  272.         setDirty(true);
  273.     }
  274.  
  275.     /** Returns the TextField's font.
  276.       * @see #setFont
  277.       */
  278.     public Font font() {
  279.         return _font;
  280.     }
  281.  
  282.     /** Sets the Color of the TextField's text and redraws the TextField.
  283.       * Default text color is Color.black.
  284.       */
  285.     public void setTextColor(Color aColor) {
  286.         _textColor = aColor;
  287.         if (_textColor == null) {
  288.             _textColor = Color.black;
  289.         }
  290.         setDirty(true);
  291.     }
  292.  
  293.     /** Returns the TextField's text Color.
  294.       * @see #setTextColor
  295.       */
  296.     public Color textColor() {
  297.         return _textColor;
  298.     }
  299.  
  300.     /** Sets the TextField's background Color and redraws the TextField.
  301.       * Default background Color is Color.white.
  302.       */
  303.     public void setBackgroundColor(Color aColor) {
  304.         _backgroundColor = aColor;
  305.         if (_backgroundColor == null) {
  306.             _backgroundColor = Color.white;
  307.         }
  308.         setDirty(true);
  309.     }
  310.  
  311.     /** Returns the TextField's background Color.
  312.       * @see #setBackgroundColor
  313.       */
  314.     public Color backgroundColor() {
  315.         return _backgroundColor;
  316.     }
  317.  
  318.     /** Sets the Color the TextField uses to indicate selection and redraws the
  319.       * TextField.  Default selection Color is Color.lightGray.
  320.       */
  321.     public void setSelectionColor(Color aColor) {
  322.         _selectionColor = aColor;
  323.         if (_selectionColor == null) {
  324.             _selectionColor = Color.lightGray;
  325.         }
  326.         setDirty(true);
  327.     }
  328.  
  329.     /** Returns the TextField's selection Color.
  330.       * @see #setSelectionColor
  331.       */
  332.     public Color selectionColor() {
  333.         return _selectionColor;
  334.     }
  335.  
  336.     /** Sets the Color of the TextField's caret.  Default is Color.black.
  337.       */
  338.     public void setCaretColor(Color aColor) {
  339.         _caretColor = aColor;
  340.         if (_caretColor == null) {
  341.             _caretColor = Color.black;
  342.         }
  343.     }
  344.  
  345.     /** Returns the TextField's caret Color.
  346.       * @see #setCaretColor
  347.       */
  348.     public Color caretColor() {
  349.         return _caretColor;
  350.     }
  351.  
  352.     /** Sets the Border the TextField draws around its perimeter.
  353.       * @see Border
  354.       */
  355.     public void setBorder(Border newBorder) {
  356.         if (newBorder == null)
  357.             newBorder = EmptyBorder.emptyBorder();
  358.  
  359.         border = newBorder;
  360.     }
  361.  
  362.     /** Returns the TextField's Border.
  363.       * @see #setBorder
  364.       */
  365.     public Border border() {
  366.         return border;
  367.     }
  368.  
  369.     /** Configures the TextField to draw its text with a drop shadow.
  370.       */
  371.     public void setDrawsDropShadow(boolean flag) {
  372.         _shadowed = flag;
  373.         setDirty(true);
  374.     }
  375.  
  376.     /** Returns <b>true</b> if the TextField draws its text with a drop shadow.
  377.       * @see #setDrawsDropShadow
  378.       */
  379.     public boolean drawsDropShadow() {
  380.         return _shadowed;
  381.     }
  382.  
  383.     /** Sets the justification (Graphics.LEFT_JUSTIFIED,
  384.       * Graphics.CENTERED, Graphics.RIGHT_JUSTIFIED) the
  385.       * TextField uses to draw its text.
  386.       */
  387.     public void setJustification(int aJustification) {
  388.         if (aJustification < Graphics.LEFT_JUSTIFIED ||
  389.             aJustification > Graphics.RIGHT_JUSTIFIED) {
  390.             return;
  391.         }
  392.  
  393.         if( aJustification != _justification ) {
  394.            _justification = aJustification;
  395.            _scrollOffset  = 0;
  396.         }
  397.     }
  398.  
  399.     /** Returns the justification the TextField uses to draw its text.
  400.       */
  401.     public int justification() {
  402.         return _justification;
  403.     }
  404.  
  405.     /** Overridden to automatically remove the TextField's Border if
  406.       * <b>flag</b> is <b>true</b>.
  407.       */
  408.     public void setTransparent(boolean flag) {
  409.         transparent = flag;
  410.         if (transparent) {
  411.             setBorder(null);
  412.         }
  413.     }
  414.  
  415.     /** Overridden to return <b>true</b> if the TextField is transparent.
  416.       * @see #setTransparent
  417.       */
  418.     public boolean isTransparent() {
  419.         return transparent;
  420.     }
  421.  
  422.  
  423. /* behavioral attributes */
  424.  
  425.     /** Configures the TextField to allow the user to select its text.
  426.       */
  427.     public void setSelectable(boolean flag) {
  428.         RootView        rootView;
  429.  
  430.         if (_selectable != flag) {
  431.             _selectable = flag;
  432.             wantsAutoscrollEvents = flag;
  433.             if (!_selectable && _scrollOffset != 0) {
  434.                 _scrollOffset = 0;
  435.                 drawInterior();
  436.             }
  437.  
  438.             rootView = rootView();
  439.             if (rootView != null) {
  440.                 rootView.updateCursor();
  441.             }
  442.         }
  443.     }
  444.  
  445.     /** Returns <b>true</b> if the TextField allows the user to select its
  446.       * text.
  447.       * @see #setSelectable
  448.       */
  449.     public boolean isSelectable() {
  450.         return _selectable;
  451.     }
  452.  
  453.     /** Overridden to return <B>true</B> if the TextField wants to
  454.       * automatically receive mouse dragged Events when the user clicks and
  455.       * drags outside of its bounds.
  456.       */
  457.     public boolean wantsAutoscrollEvents() {
  458.         return wantsAutoscrollEvents;
  459.     }
  460.  
  461.     /** Configures the TextField to wrap its contents if too long to fit
  462.       * on a single line.
  463.       */
  464.     public void setWrapsContents(boolean flag) {
  465.         _canWrap = flag;
  466.         if( flag && isEditable())
  467.             setEditable(false);
  468.         drawInterior();
  469.     }
  470.  
  471.     /** Returns <b>true</b> if the TextField wraps its contents if too long to
  472.       * fit on a single line.
  473.       * @see #setWrapsContents
  474.       */
  475.     public boolean wrapsContents() {
  476.         return _canWrap;
  477.     }
  478.  
  479.    /** Configures the TextField to allow the user to edit its text. */
  480.     public void setEditable(boolean aFlag) {
  481.         if (_editable != aFlag) {
  482.             _editable = aFlag;
  483.             setSelectable(aFlag);
  484.             if( aFlag && wrapsContents() )
  485.                 setWrapsContents(false);
  486.         }
  487.     }
  488.  
  489.     /** Returns <b>true</b> if the TextField is editable.
  490.       * @see #setEditable
  491.       */
  492.     public boolean isEditable() {
  493.         return _editable;
  494.     }
  495.  
  496.     /** Returns <b>true</b> if the TextField's contents are currently being
  497.       * edited.
  498.       */
  499.     public boolean isBeingEdited() {
  500.         return _editing;
  501.     }
  502.  
  503.     /** Overridden to return TEXT_CURSOR when the TextField is selectable or
  504.       * editable.
  505.       */
  506.     public int cursorForPoint(int x, int y) {
  507.         if (isEditable() || isSelectable()) {
  508.             return TEXT_CURSOR;
  509.         }
  510.         return ARROW_CURSOR;
  511.     }
  512.  
  513.  
  514.  
  515. /* other attributes */
  516.  
  517.     /** Sets the TextField's owner, the object that it notifies of important
  518.       * events such as receiving a new key Event.
  519.       * @see TextFieldOwner
  520.       */
  521.     public void setOwner(TextFieldOwner owner) {
  522.         _owner = owner;
  523.     }
  524.  
  525.     /** Returns the TextField's owner.
  526.       * @see #setOwner
  527.       */
  528.     public TextFieldOwner owner() {
  529.         return _owner;
  530.     }
  531.  
  532.     /** Sets the TextField's filter, the object that inspects each key
  533.       * Event received by the TextField.
  534.       * @see TextFilter
  535.       */
  536.     public void setFilter(TextFilter aFilter) {
  537.         _filter = aFilter;
  538.     }
  539.  
  540.     /** Returns the TextField's text filter.
  541.       * @see #setFilter
  542.       */
  543.     public TextFilter filter() {
  544.         return _filter;
  545.     }
  546.  
  547.     /** Sets the Target and the command it should receive when the TextField's
  548.       * contents change. This command is sent each time the user changes the
  549.       * text inside the TextField.
  550.       */
  551.     public void setContentsChangedCommandAndTarget(String aCommand,
  552.                                                    Target aTarget) {
  553.         _contentsChangedCommand = aCommand;
  554.         _contentsChangedTarget = aTarget;
  555.     }
  556.  
  557.     /** Returns the contents changed Target.
  558.       * @see #setContentsChangedCommandAndTarget
  559.       */
  560.     public Target contentsChangedTarget() {
  561.         return _contentsChangedTarget;
  562.     }
  563.  
  564.     /** Returns the contents changed command.
  565.       * @see #setContentsChangedCommandAndTarget
  566.       */
  567.     public String contentsChangedCommand() {
  568.         return _contentsChangedCommand;
  569.     }
  570.  
  571.     /** Sets the TextField whose text is selected when the TextField
  572.       * receives a Return or Tab key Event.
  573.       */
  574.     public void setTabField(TextField aTextField) {
  575.         if (aTextField == null) {
  576.             _tabTarget = null;
  577.             _tabCommand = null;
  578.         } else {
  579.             _tabTarget = aTextField;
  580.             _tabCommand = SELECT_TEXT;
  581.         }
  582.         invalidateKeyboardSelectionOrder();
  583.     }
  584.  
  585.     /** Returns the TextField whose text is selected when the TextField
  586.       * receives a Return or Tab key Event.
  587.       * @see #setTabField
  588.       */
  589.     public TextField tabField() {
  590.         if (_tabTarget instanceof TextField) {
  591.             return (TextField)_tabTarget;
  592.         }
  593.  
  594.         return null;
  595.     }
  596.  
  597.     /** Sets the TextField whose text is selected when the TextField
  598.       * receives a Backtab key Event.
  599.       */
  600.     public void setBacktabField(TextField aTextField) {
  601.         if (aTextField == null) {
  602.             _backtabTarget = null;
  603.             _backtabCommand = null;
  604.         } else if (aTextField != this) {
  605.             _backtabTarget = aTextField;
  606.             _backtabCommand = SELECT_TEXT;
  607.         }
  608.         invalidateKeyboardSelectionOrder();
  609.     }
  610.  
  611.     /** Returns the TextField whose text is selected when the TextField
  612.       * receives a Backtab key Event.
  613.       * @see #setBacktabField
  614.       */
  615.     public TextField backtabField() {
  616.         if (_backtabTarget instanceof TextField) {
  617.             return (TextField)_backtabTarget;
  618.         }
  619.  
  620.         return null;
  621.     }
  622.  
  623.     /** Sets the Target that should receive a command when the textfield
  624.      *  commit to a new value. The textfield commit to a new value in the
  625.      *  following situations:
  626.      *  <OL>
  627.      *  <LI> The user types Return.
  628.      *  <LI> Contents has changed and the user press tab or backtab
  629.      *  <LI> Contents has changed and the textfield loses focus
  630.      *  </OL>
  631.      *  If a more precise understanding of why the textfield is ending
  632.      *  the editing session is required, you need to use TextFieldOwner.
  633.      */
  634.     public void setTarget(Target aTarget) {
  635.         _commitTarget = aTarget;
  636.     }
  637.  
  638.     /** Sets the command the Target should receive when the
  639.      *  editing ends. The editing ends when the user types return,
  640.      *  tab, backtab or select something else.
  641.      */
  642.     public void setCommand(String aCommand) {
  643.         _commitCommand = aCommand;
  644.     }
  645.  
  646.     /** Returns the Return Target.
  647.       * @see #setTarget
  648.       */
  649.     public Target target() {
  650.         return _commitTarget;
  651.     }
  652.  
  653.     /** Returns the Return command.
  654.       * @see #setCommand
  655.       */
  656.     public String command() {
  657.         return _commitCommand;
  658.     }
  659.  
  660.  
  661. /* content */
  662.  
  663.     /** Sets the contents of the TextField to <b>aString</b> */
  664.     public void setStringValue(String aString) {
  665.         if (aString != null && aString.equals(stringValue())) {
  666.             if (isBeingEdited()) {
  667.                 cancelEditing();
  668.             }
  669.             return;
  670.         }
  671.  
  672.         if(aString == null)
  673.             aString = "";
  674.  
  675.         replaceRangeWithString(new Range(0,charCount()),aString);
  676.  
  677.         _oldContents = null;
  678.  
  679.         if (isBeingEdited()) {
  680.             cancelEditing();
  681.         } else {
  682.             setDirty(true);
  683.         }
  684.     }
  685.  
  686.     /** Returns the TextField's contents.
  687.       * @see #setStringValue
  688.       */
  689.     public String stringValue() {
  690.         if (_contents == null) {
  691.             return "";
  692.         }
  693.         return _contents.toString();
  694.     }
  695.  
  696.     /** Replaces the string enclosed by <b>aRange</b> with <b>aString</b>.  If
  697.       * <b>aRange</b> is a null range, this method inserts <b>aString</b> into
  698.       * the text.  If <b>aString</b> is <b>null</b> or the empty string, this
  699.       * method removes the text defined by <b>aRange</b>.
  700.       */
  701.     public void replaceRangeWithString(Range aRange,String aString) {
  702.         String contents = stringValue();
  703.         Range  r = new Range();
  704.         String before,after;
  705.  
  706.         r.index  = aRange.index;
  707.         r.length = aRange.length;
  708.         r.intersectWith(new Range(0,contents.length()));
  709.  
  710.         if( r.isNullRange()) {
  711.             r.index = contents.length();
  712.             r.length= 0;
  713.         }
  714.  
  715.         before = contents.substring(0,r.index);
  716.         after  = contents.substring(r.index+r.length);
  717.  
  718.         if( aString != null )
  719.             _contents = new FastStringBuffer(before + aString + after );
  720.         else
  721.             _contents = new FastStringBuffer(before + after);
  722.  
  723.         if( isBeingEdited() ) {
  724.             Range selectedRange;
  725.  
  726.             r.index = 0;
  727.             r.length = _contents.length();
  728.             selectedRange = selectedRange();
  729.             selectedRange.intersectWith(r);
  730.             if( selectedRange.isNullRange())
  731.                 selectRange(new Range(_contents.length,0));
  732.             else
  733.                 selectRange(selectedRange);
  734.         } else
  735.             setDirty(true);
  736.     }
  737.  
  738.     /** Returns the string included in <b>aRange</b>. */
  739.     public String stringForRange(Range aRange) {
  740.         String contents = stringValue();
  741.         Range r = new Range();
  742.         r.index = aRange.index;
  743.         r.length = aRange.length;
  744.         r.intersectWith( new Range(0,contents.length()));
  745.         if( r.isNullRange())
  746.             return "";
  747.         return contents.substring(r.index,r.index+r.length());
  748.     }
  749.  
  750.     /** Returns the selected portion of the TextField's contents.  If none,
  751.       * returns the empty string.
  752.       * @see #stringValue
  753.       */
  754.     public String selectedStringValue() {
  755.         int     start, stop;
  756.  
  757.         if (hasInsertionPoint()) {
  758.             return "";
  759.         }
  760.  
  761.         start = selectionStart();
  762.         stop = selectionStop();
  763.  
  764.         if (start == -1 || stop == -1) {
  765.             return "";
  766.         }
  767.  
  768.         if (stop == _contents.length()) {
  769.             return _contents.toString().substring(start);
  770.         }
  771.  
  772.         return _contents.toString().substring(start, stop);
  773.     }
  774.  
  775.     /** Sets the contents of the TextField to the string version of
  776.       * <b>anInt</b>.
  777.       */
  778.     public void setIntValue(int anInt) {
  779.         setStringValue(Integer.toString(anInt));
  780.     }
  781.  
  782.     /** Returns the integer value of the TextField's contents, or <b>0</b> if
  783.       * not a number.
  784.       */
  785.     public int intValue() {
  786.         return parseInt(_contents.toString());
  787.     }
  788.  
  789.     /** Returns <b>true</b> if the TextField contains no text.
  790.       */
  791.     public boolean isEmpty() {
  792.         return (charCount() == 0);
  793.     }
  794.  
  795.     /** Returns the number of characters the TextField contains. */
  796.     public int charCount() {
  797.         return _contents.length();
  798.     }
  799.  
  800.     /** Returns the baseline of the first line of text.
  801.       */
  802.     public int baseline() {
  803.         String  contentString;
  804.         Rect    interiorRect;
  805.         Size    stringSize;
  806.         int     y;
  807.  
  808.         contentString = drawableString();
  809.         stringSize = _font.fontMetrics().stringSize(contentString);
  810.  
  811.         interiorRect = Rect.newRect();
  812.         border.computeInteriorRect(0, 0, bounds.width, bounds.height,
  813.                                    interiorRect);
  814.         y = interiorRect.maxY() -
  815.                         (interiorRect.height - stringSize.height) / 2 -
  816.                         _font.fontMetrics().descent();
  817.  
  818.         Rect.returnRect(interiorRect);
  819.  
  820.         return y;
  821.     }
  822.  
  823.  
  824.  
  825. /* selection */
  826.  
  827.     /** Selects characters in the Range <b>aRange</b>, unless the TextField is
  828.       * not selectable.
  829.       */
  830.     public void selectRange(Range aRange) {
  831.         if( aRange.length < 0 || aRange.index < 0 )
  832.             throw new InconsistencyException("TextField - invalid range: " +
  833.                                                                     aRange);
  834.  
  835.         selectRange(aRange.index,aRange.index + aRange.length);
  836.     }
  837.  
  838.     /** Selects characters <b>start</b> through <b>stop</b> of the
  839.       * TextField's contents, unless the TextField is not selectable.
  840.       * Override this method if you need to know when the selection changed.
  841.       *
  842.       */
  843.     protected void selectRange(int start, int stop) {
  844.         if (!isSelectable()) {
  845.             return;
  846.         }
  847.  
  848.         if (start < 0) {
  849.             start = 0;
  850.         } else if (start > _contents.length()) {
  851.             start = _contents.length();
  852.         }
  853.         if (stop < 0) {
  854.             stop = 0;
  855.         } else if (stop > _contents.length()) {
  856.             stop = _contents.length();
  857.         }
  858.  
  859.         _selectionAnchorChar = start;
  860.         _selectionEndChar = stop;
  861.  
  862.         if (isEditable() && !isBeingEdited()) {
  863.             _startEditing(true);
  864.         }
  865.  
  866.         // Need to refresh here since selection not visible
  867.         // when textfield does not have the focus
  868.         drawInterior();
  869.     }
  870.  
  871.     /** Selects the TextField's contents, unless it is not selectable.
  872.       * @see #selectRange
  873.       */
  874.     public void selectText() {
  875.         selectRange(0, charCount());
  876.     }
  877.  
  878.     /** Places the TextField's insertion point at <b>position</b>, unless
  879.       * the TextField is not selectable.
  880.       */
  881.     public void setInsertionPoint(int position) {
  882.         selectRange(position, position);
  883.     }
  884.  
  885.     int selectionAnchorPoint() {
  886.         return _selectionAnchorChar;
  887.     }
  888.  
  889.     int selectionEndPoint() {
  890.         return _selectionEndChar;
  891.     }
  892.  
  893.     /** Returns a Range containing the current selection. If no selection
  894.       * exists, this method returns a null range.
  895.       */
  896.     public Range selectedRange() {
  897.         if( hasInsertionPoint() ) {
  898.             return new Range(_selectionAnchorChar,0);
  899.         }
  900.         if( _selectionAnchorChar == -1 ||
  901.             _selectionEndChar == -1 )
  902.             return new Range();
  903.         else
  904.             return Range.rangeFromIndices(selectionStart(),selectionStop());
  905.     }
  906.  
  907.     /** Returns the location of the first selected character, or <b>-1</b> if no
  908.       * selection or insertion point.
  909.       */
  910.     int selectionStart() {
  911.         return (_selectionAnchorChar < _selectionEndChar) ?
  912.                                     _selectionAnchorChar : _selectionEndChar;
  913.     }
  914.  
  915.     /** Returns the location of the last selected character, or <b>-1</b> if no
  916.       * selection or insertion point.
  917.       */
  918.     int selectionStop() {
  919.         return (_selectionAnchorChar < _selectionEndChar) ?
  920.                                     _selectionEndChar : _selectionAnchorChar;
  921.     }
  922.  
  923.     /** Returns <b>true</b> if the TextField has a selection. */
  924.     public boolean hasSelection() {
  925.         return (_selectionAnchorChar != _selectionEndChar);
  926.     }
  927.  
  928.     /** Returns <b>true</b> if the TextField has an insertion point. */
  929.     public boolean hasInsertionPoint() {
  930.         return (_selectionAnchorChar == _selectionEndChar &&
  931.                 _selectionAnchorChar != -1);
  932.     }
  933.  
  934.     Rect caretRect() {
  935.         FontMetrics  fontMetrics;
  936.         Rect            interiorRect;
  937.         int             y1, y2, cutoff;
  938.  
  939.         fontMetrics = _font.fontMetrics();
  940.         if (fontMetrics == null) {
  941.             return null;
  942.         }
  943.  
  944.         interiorRect = interiorRect();
  945.         y2 = interiorRect.maxY() - (interiorRect.height - _fontHeight) / 2;
  946.  
  947.         y1 = y2 - fontMetrics.charHeight();
  948.         cutoff = border.topMargin();
  949.         if (y1 < cutoff) {
  950.             y1 = cutoff;
  951.         }
  952.  
  953.         Rect.returnRect(interiorRect);
  954.  
  955.         /* we need to take endChar to make scroll offset computation work */
  956.         return Rect.newRect(xPositionOfCharacter(_selectionEndChar), y1, 1,
  957.                             y2 - y1);
  958.     }
  959.  
  960.     Rect interiorRect() {
  961.         Rect interiorRect = Rect.newRect();
  962.  
  963.         border.computeInteriorRect(0, 0, width(), height(), interiorRect);
  964.         return interiorRect;
  965.     }
  966.  
  967.     Rect rectForRange(int start, int stop) {
  968.         Rect    tmpRect;
  969.         int     startX;
  970.  
  971.         startX = xPositionOfCharacter(start);
  972.         tmpRect = interiorRect();
  973.         tmpRect.setBounds(startX, tmpRect.y,
  974.                           xPositionOfCharacter(stop) - startX + 1,
  975.                           tmpRect.height);
  976.  
  977.         return tmpRect;
  978.     }
  979.  
  980.  
  981.  
  982. /* drawing */
  983.  
  984.     /** Returns the X-coordinate of character number <b>charNumber</b>. */
  985.     public int xPositionOfCharacter(int charNumber) {
  986.         FontMetrics  fontMetrics;
  987.         String       contentString;
  988.         int          startX;
  989.         int          stringWidth;
  990.  
  991.         fontMetrics = _font.fontMetrics();
  992.         contentString = drawableString();
  993.         stringWidth   = fontMetrics.stringWidth(contentString);
  994.  
  995.         startX = absoluteXOriginForStringWithWidth(stringWidth);
  996.  
  997.         if( charNumber <= 0 )
  998.             return startX;
  999.         else
  1000.             return startX + fontMetrics.stringWidth(
  1001.                              contentString.substring(0, charNumber));
  1002.     }
  1003.  
  1004.     /** Returns the character number for X-coordinate <b>x</b>. */
  1005.     public int charNumberForPoint(int x) {
  1006.         FontMetrics     fontMetrics;
  1007.         String          contentString;
  1008.         int             contentLength, stringWidth, i, width,oldWidth,delta;
  1009.         int             startX;
  1010.  
  1011.         contentLength = _contents.length();
  1012.         if (contentLength == 0) {
  1013.             return 0;
  1014.         }
  1015.  
  1016.         fontMetrics = _font.fontMetrics();
  1017.         contentString = drawableString();
  1018.  
  1019.         stringWidth = fontMetrics.stringWidth(contentString);
  1020.  
  1021.         startX = absoluteXOriginForStringWithWidth(stringWidth);
  1022.         if (x < startX) {
  1023.             return 0;
  1024.         } else if (x > (startX + stringWidth)) {
  1025.             return contentLength;
  1026.         }
  1027.  
  1028.         oldWidth = 0;
  1029.         for (i = 1; i < contentLength; i++) {
  1030.             width = fontMetrics.stringWidth(contentString.substring(0, i));
  1031.             delta = width - oldWidth;
  1032.             if (x <= (startX + width)) {
  1033.                 if (x > (startX + oldWidth + (delta / 2))) {
  1034.                     return i;
  1035.                 } else {
  1036.                     return i - 1;
  1037.                 }
  1038.             }
  1039.  
  1040.             oldWidth = width;
  1041.         }
  1042.  
  1043.         return contentLength;
  1044.     }
  1045.  
  1046.     void drawViewCaret(Graphics g) {
  1047.         Rect    caretRect;
  1048.  
  1049.         if (!_caretShowing || _selectionAnchorChar == -1 ||
  1050.             _selectionAnchorChar != _selectionEndChar ||
  1051.             !hasFocus ) {
  1052.             return;
  1053.         }
  1054.  
  1055.         g.setColor(_caretColor);
  1056.         caretRect = caretRect();
  1057.         g.drawLine(caretRect.x, caretRect.y, caretRect.x, caretRect.maxY()-1);
  1058.         Rect.returnRect(caretRect);
  1059.     }
  1060.  
  1061.     Vector stringVectorForContents(int maxWidth) {
  1062.         int charWidths[];
  1063.         FontMetrics fm;
  1064.         int currentWidth;
  1065.         Vector result = new Vector();
  1066.         String contents = drawableString();
  1067.         int    index,firstIndex,length,lastSpace;
  1068.         int    size;
  1069.         char   buf[] = new char[1];
  1070.         char   ch;
  1071.  
  1072.         fm = font().fontMetrics();
  1073.         charWidths = fm.widthsArray();
  1074.  
  1075.         index = 0;
  1076.         length = contents.length();
  1077.         firstIndex = index;
  1078.         currentWidth = 0;
  1079.         lastSpace = -1;
  1080.  
  1081.         while( index < length ) {
  1082.             ch = contents.charAt(index);
  1083.             if( ch == ' ' || ch == '\t' )
  1084.                 lastSpace = index;
  1085.             if( ch == '\n' ) {
  1086.                 result.addElement(contents.substring(firstIndex,index));
  1087.                 index++;
  1088.                 firstIndex = index;
  1089.                 currentWidth = 0;
  1090.                 lastSpace = -1;
  1091.             } else {
  1092.                 if( ch < 256 )
  1093.                     currentWidth += charWidths[ch];
  1094.                 else {
  1095.                     buf[0] = ch;
  1096.                     currentWidth += fm.stringWidth(new String(buf));
  1097.                 }
  1098.                 if( currentWidth > maxWidth ) {
  1099.                     if( index == firstIndex ) {/* One char per line minimum */
  1100.                         result.addElement(contents.substring(firstIndex,firstIndex+1));
  1101.                         index++;
  1102.                         firstIndex = index;
  1103.                     } if( lastSpace == -1 ) {
  1104.                         result.addElement(contents.substring(firstIndex,index));
  1105.                         firstIndex = index;
  1106.                     } else {
  1107.                         result.addElement(contents.substring(firstIndex,lastSpace));
  1108.                         firstIndex = lastSpace+1;
  1109.                         index = firstIndex;
  1110.                     }
  1111.                     currentWidth = 0;
  1112.                     lastSpace = -1;
  1113.                 } else
  1114.                     index++;
  1115.             }
  1116.         }
  1117.  
  1118.         if( firstIndex < length) {
  1119.             result.addElement(contents.substring(firstIndex));
  1120.         }
  1121.         return result;
  1122.     }
  1123.  
  1124.  
  1125.     /** Draws the String at position (<b>x</b>, <b>y</b>).  You never call this
  1126.       * method directly, but should override to produce custom string drawing.
  1127.       */
  1128.     public void drawViewStringAt(Graphics g, String aString, int x, int y) {
  1129.         if (_shadowed) {
  1130.             g.setColor(Color.black);
  1131.             g.drawString(aString, x + 2, y + 2);
  1132.         }
  1133.         g.setColor(_textColor);
  1134.         g.drawString(aString, x, y);
  1135.     }
  1136.  
  1137.     int absoluteXOriginForStringWithWidth(int stringWidth) {
  1138.         int x;
  1139.         if (_justification == Graphics.RIGHT_JUSTIFIED)
  1140.             x = width() - border.rightMargin() - rightIndent()
  1141.                 - stringWidth - _scrollOffset;
  1142.         else if (_justification == Graphics.CENTERED)
  1143.             x = border.leftMargin() + leftIndent() +
  1144.                 ((width() - (border.widthMargin() + widthIndent())
  1145.                   - stringWidth) / 2) - _scrollOffset;
  1146.         else
  1147.             x = border.leftMargin() + leftIndent() - _scrollOffset;
  1148.         return x;
  1149.     }
  1150.  
  1151.  
  1152.     void drawViewLine(Graphics g, String aString, Size stringSize, int y) {
  1153.         int     x, offset;
  1154.  
  1155.         if (stringSize == null) {
  1156.             stringSize = _font.fontMetrics().stringSize(aString);
  1157.         }
  1158.  
  1159.         x = absoluteXOriginForStringWithWidth(stringSize.width);
  1160.  
  1161.         drawViewStringAt(g, aString, x, y);
  1162.     }
  1163.  
  1164.     /** Draws the portion of the TextField's interior specified by
  1165.       * <b>interiorRect</b>.  Calls <b>drawViewStringAt()</b> to draw the text.
  1166.       * You never call this method directly, but should override to produce
  1167.       * custom TextField drawing.
  1168.       */
  1169.     public void drawViewInterior(Graphics g, Rect interiorRect) {
  1170.         Vector          stringVector;
  1171.         String          contentString;
  1172.         Size            stringSize;
  1173.         Rect            caretRect;
  1174.         int             y, x1, x2, i, count, delta;
  1175.  
  1176.         /* get the baseline of the first line of text */
  1177.         y = baseline();
  1178.  
  1179.         /* clip to within bezel */
  1180.         g.pushState();
  1181.         g.setClipRect(interiorRect);
  1182.  
  1183.         /* draw the background */
  1184.         if (!isTransparent()) {
  1185.             /* we want different color for non-editable, but no way to
  1186.                 * enforce it here and get the right behavior for people who
  1187.                 * don't want to follow the "standard" look; developer should
  1188.                 * explicitly set the background non-editable and selection
  1189.                 * colors
  1190.                 */
  1191.             g.setColor(_backgroundColor);
  1192.             g.fillRect(interiorRect);
  1193.         }
  1194.  
  1195.       /* draw the selection rectangle */
  1196.         if (_selectionAnchorChar != _selectionEndChar &&
  1197.             hasFocus && isSelectable()) {
  1198.             x1 = xPositionOfCharacter(selectionStart());
  1199.             x2 = xPositionOfCharacter(selectionStop());
  1200.             caretRect = caretRect();
  1201.  
  1202.             g.setColor(_selectionColor);
  1203.             g.fillRect(x1, caretRect.y, x2 - x1, caretRect.height);
  1204.  
  1205.             Rect.returnRect(caretRect);
  1206.         }
  1207.  
  1208.         /* draw the contents */
  1209.         g.setFont(_font);
  1210.  
  1211.         contentString = drawableString();
  1212.  
  1213.         stringSize = _font.fontMetrics().stringSize(contentString);
  1214.  
  1215.         if (!_canWrap || isEditable()) {
  1216.             drawViewLine(g, contentString, stringSize, y);
  1217.         } else {
  1218.             stringVector = stringVectorForContents(interiorRect.width);
  1219.             count = stringVector.count();
  1220.  
  1221.             if (count > 1) {
  1222.                 y += (interiorRect.height - stringSize.height) / 2;
  1223.                 delta = (interiorRect.height -
  1224.                                 (int)(stringSize.height * count)) / 2;
  1225.                 y -= delta + (count - 1) * stringSize.height;
  1226.             }
  1227.             for (i = 0; i < count; i++) {
  1228.                 drawViewLine(g, (String)stringVector.elementAt(i), null, y);
  1229.                 y += stringSize.height;
  1230.             }
  1231.         }
  1232.  
  1233.         if (isBeingEdited() && _caretShowing) {
  1234.             drawViewCaret(g);
  1235.         }
  1236.         g.popState();
  1237.     }
  1238.  
  1239.     /** Draws the TextField's border using its Border.  You never call this
  1240.       * method directly, but should override to produce custom border drawing.
  1241.       */
  1242.     public void drawViewBorder(Graphics g) {
  1243.         if (border != null) {
  1244.             border.drawInRect(g, 0, 0, width(), height());
  1245.             return;
  1246.         }
  1247.  
  1248.         // ALERT why drawing the background from here?
  1249.  
  1250.         if (!isTransparent() && _backgroundColor != null) {
  1251.             g.setColor(_backgroundColor);
  1252.             g.fillRect(0, 0, width(), height());
  1253.         }
  1254.     }
  1255.  
  1256.     /** Draws the TextField.  Calls <b>drawViewBorder()</b> and
  1257.       * <b>drawViewInterior()</b>.  You never call this method directly - call
  1258.       * the TextField's <b>draw()</b> method to draw the TextField.
  1259.       */
  1260.     public void drawView(Graphics g) {
  1261.         Rect    interiorRect;
  1262.  
  1263.         drawViewBorder(g);
  1264.  
  1265.         interiorRect = interiorRect();
  1266.         drawViewInterior(g, interiorRect);
  1267.         Rect.returnRect(interiorRect);
  1268.     }
  1269.  
  1270.     /* Redraws the area occupied by the caret. */
  1271.     void drawCaret() {
  1272.         Rect    caretRect;
  1273.  
  1274.         caretRect = caretRect();
  1275.         addDirtyRect(caretRect);
  1276.         Rect.returnRect(caretRect);
  1277.     }
  1278.  
  1279.     /* Hides the caret. */
  1280.     void hideCaret() {
  1281.         _caretShowing = false;
  1282.         drawCaret();
  1283.     }
  1284.  
  1285.     /* Shows the caret. */
  1286.     void showCaret() {
  1287.         _caretShowing = true;
  1288.         drawCaret();
  1289.     }
  1290.  
  1291.     /** Redraws the TextField's interior. */
  1292.     public void drawInterior() {
  1293.         Rect    interiorRect;
  1294.  
  1295.         interiorRect = interiorRect();
  1296.         addDirtyRect(interiorRect);
  1297.         Rect.returnRect(interiorRect);
  1298.     }
  1299.  
  1300.  
  1301.  
  1302. /* mouse events */
  1303.     /** Overriden to return <b>true</b>.
  1304.     public boolean wantsMouseTrackingEvents() {
  1305.         return true;
  1306.     }
  1307.  
  1308.     /** Overridden to process mouse Events within the TextField. */
  1309.     public boolean mouseDown(MouseEvent event) {
  1310.         boolean shouldHideCursor = true;
  1311.         Rect            redrawRect = null;
  1312.         boolean         caretWasShowing;
  1313.         Range r,wasSelected;
  1314.  
  1315.         _clickCount = event.clickCount();
  1316.         if( _clickCount > 3 )
  1317.             return true;
  1318.  
  1319.         if (!isSelectable()) {
  1320.             return false;
  1321.         }
  1322.  
  1323.         if (!isBeingEdited()) {
  1324.             if(isEditable())
  1325.                 _startEditing(true);
  1326.             else if(isSelectable())   /** Should grab focus when only selectable
  1327.                                         * for selection display exclusion
  1328.                                         */
  1329.                 _startEditing(false);
  1330.         }
  1331.  
  1332.         /** Calling start editing might change the focus.
  1333.          *  changing the focus might popup another window
  1334.          *  in this case we'll never see a mouse up.
  1335.          *  If the mouse is up we should not hide the
  1336.          *  cursor, we should just change the selection.
  1337.          */
  1338.         if(!rootView().mouseStillDown()) {
  1339.             int charNumber = charNumberForPoint(event.x);
  1340.             _clickCount = 0;
  1341.             selectRange(new Range(charNumber,0));
  1342.             if (!hasSelection() && isEditable()) {
  1343.                 _caretShowing = _canBlink = true;
  1344.                 drawCaret();
  1345.                 _startBlinkTimer();
  1346.             }
  1347.             return true;
  1348.         }
  1349.  
  1350.  
  1351.         /** This should be performed after _startEditing to
  1352.          *  take in account this last change.
  1353.          */
  1354.         caretWasShowing = _caretShowing;
  1355.  
  1356.         _canBlink = _caretShowing = false;
  1357.         _mouseDragging = true;
  1358.  
  1359.         if (hasSelection()) {
  1360.             redrawRect = rectForRange(selectionStart(), selectionStop());
  1361.         } else if (caretWasShowing) {
  1362.             hideCaret();
  1363.         }
  1364.  
  1365.         wasSelected = selectedRange();
  1366.  
  1367.         if(event.isShiftKeyDown() && _clickCount == 1) {
  1368.             _selectionEndChar = charNumberForPoint(event.x);
  1369.             if( redrawRect != null )
  1370.                 redrawRect.unionWith(rectForRange(selectionStart(),selectionStop()));
  1371.             else
  1372.                 redrawRect = rectForRange(selectionStart(),selectionStop());
  1373.         } else {
  1374.             _selectionAnchorChar = _selectionEndChar = _initialAnchorChar =
  1375.               charNumberForPoint(event.x);
  1376.         }
  1377.  
  1378.         switch( _clickCount ) {
  1379.         case 2:
  1380.             r = groupForIndex(_selectionAnchorChar);
  1381.             if(!r.isNullRange()) {
  1382.               if(event.isShiftKeyDown()) {
  1383.                   Range otherRange = new Range(wasSelected);
  1384.                   otherRange.unionWith(r);
  1385.                   selectRange(otherRange);
  1386.               } else
  1387.                   selectRange(r);
  1388.             }
  1389.             redrawRect = null;
  1390.             break;
  1391.         case 3:
  1392.             selectRange(new Range(0,charCount()));
  1393.             redrawRect = null;
  1394.             break;
  1395.         default:
  1396.             break;
  1397.         }
  1398.  
  1399.         if (redrawRect != null) {
  1400.             addDirtyRect(redrawRect);
  1401.             Rect.returnRect(redrawRect);
  1402.         }
  1403.  
  1404.         return true;
  1405.     }
  1406.  
  1407.     void _computeScrollOffset() {
  1408.         Rect    caretRect,interiorRect;
  1409.         int     leftOffset, rightOffset;
  1410.         String  contentString;
  1411.  
  1412.         if (!isScrollable)  {
  1413.             _scrollOffset = 0;
  1414.             return;
  1415.         }
  1416.  
  1417.         leftOffset = border.leftMargin() + leftIndent();
  1418.         rightOffset = border.rightMargin() + rightIndent();
  1419.  
  1420.         caretRect = caretRect();
  1421.         interiorRect = interiorRect();
  1422.  
  1423.         contentString = drawableString();
  1424.  
  1425.         /* Always cancel any scrolling if the text now fit */
  1426.         if( (interiorRect.width - (leftIndent() + rightIndent())) >
  1427.             _font.fontMetrics().stringWidth(contentString)) {
  1428.             _scrollOffset = 0;
  1429.             return;
  1430.         }
  1431.  
  1432.         if (caretRect.x >= leftOffset &&
  1433.             caretRect.x < bounds.width - rightOffset) {
  1434.             Rect.returnRect(caretRect);
  1435.  
  1436.             return;
  1437.         }
  1438.  
  1439.         if (caretRect.x <  leftOffset) {
  1440.             _scrollOffset += caretRect.x - leftOffset;
  1441.         } else {
  1442.             _scrollOffset += caretRect.x - (bounds.width - rightOffset);
  1443.         }
  1444.  
  1445.         Rect.returnRect(caretRect);
  1446.     }
  1447.  
  1448.     /** Overridden to process mouse Events within the TextField. */
  1449.     public void mouseDragged(MouseEvent event) {
  1450.         Rect    redrawRect;
  1451.         Size    stringSize;
  1452.         int     oldOffset, offset, minOffset, maxOffset, sideWidths,
  1453.                 stringWidth, oldEndChar, left, right, delta = 0;
  1454.         boolean shouldRefresh = true;
  1455.  
  1456.         if (!isSelectable())
  1457.             return;
  1458.  
  1459.         /* If clickCount > 2, we have selected everything. Nothing
  1460.          * should happend during mouseDrag
  1461.          */
  1462.         if( _clickCount > 2 )
  1463.             return;
  1464.  
  1465.         oldEndChar = _selectionEndChar;
  1466.         _selectionEndChar = charNumberForPoint(event.x);
  1467.  
  1468.         if (_clickCount == 2 ) { /* Per word selection dragging */
  1469.             Range startRange  = groupForIndex(_initialAnchorChar);
  1470.             Range endRange    = groupForIndex(_selectionEndChar);
  1471.             Range unionRange  = Range.rangeFromUnion(startRange,endRange);
  1472.             if(!unionRange.isNullRange()) {
  1473.                 if( endRange.index > startRange.index ) {
  1474.                     _selectionAnchorChar = startRange.index;
  1475.                     _selectionEndChar    = endRange.index + endRange.length;
  1476.  
  1477.                 } else {
  1478.                     _selectionAnchorChar = startRange.index +
  1479.                                            startRange.length;
  1480.                     _selectionEndChar    = endRange.index;
  1481.                 }
  1482.             }
  1483.         }
  1484.  
  1485.         if (!containsPointInVisibleRect(event.x, 1)) {
  1486.             oldOffset = _scrollOffset;
  1487.             _computeScrollOffset();
  1488.             if(_scrollOffset != oldOffset ) {
  1489.                 drawInterior();
  1490.                 shouldRefresh = false;
  1491.             }
  1492.         }
  1493.  
  1494.         if (shouldRefresh && _selectionEndChar != oldEndChar) {
  1495.             if (_selectionEndChar < _selectionAnchorChar &&
  1496.                 oldEndChar > _selectionAnchorChar ||
  1497.                 _selectionEndChar > _selectionAnchorChar &&
  1498.                 oldEndChar < _selectionAnchorChar) {
  1499.                 left = selectionStart();
  1500.                 right = selectionStop();
  1501.                 if (oldEndChar < left) {
  1502.                     left = oldEndChar;
  1503.                 }
  1504.                 if (oldEndChar > right) {
  1505.                     right = oldEndChar;
  1506.                 }
  1507.             } else {
  1508.                 if (_selectionEndChar > oldEndChar) {
  1509.                     left = oldEndChar;
  1510.                     right = _selectionEndChar;
  1511.                 } else {
  1512.                     left = _selectionEndChar;
  1513.                     right = oldEndChar;
  1514.                 }
  1515.             }
  1516.  
  1517.             redrawRect = rectForRange(left, right);
  1518.             addDirtyRect(redrawRect);
  1519.             Rect.returnRect(redrawRect);
  1520.         }
  1521.     }
  1522.  
  1523.     /** Overridden to process mouse Events within the TextField. */
  1524.     public void mouseUp(MouseEvent event) {
  1525.         _mouseDragging = false;
  1526.  
  1527.         if (!hasSelection() && isEditable()) {
  1528.             _caretShowing = _canBlink = true;
  1529.             drawCaret();
  1530.         }
  1531.  
  1532.         _initialAnchorChar = -1;
  1533.         _clickCount = 0;
  1534.     }
  1535.  
  1536.  
  1537.  
  1538. /* key events */
  1539.  
  1540.     void _keyDown(KeyEvent event) {
  1541.         String          contentString;
  1542.         int             oldAnchor, oldOffset, start, condition;
  1543.         boolean         didChange, wasASelection;
  1544.  
  1545.         // THIS IS THE CAPS LOCK KEY CHAR
  1546.         if(event.key == 1022)
  1547.             return;
  1548.  
  1549.         if (event.isReturnKey() || event.isTabKey() || event.isBackTabKey()) {
  1550.             if (event.isReturnKey()) {
  1551.                 condition = TextFieldOwner.RETURN_KEY;
  1552.             } else if (event.isTabKey()) {
  1553.                 condition = TextFieldOwner.TAB_KEY;
  1554.             } else {
  1555.                 condition = TextFieldOwner.BACKTAB_KEY;
  1556.             }
  1557.             if (_owner != null &&
  1558.                 !_owner.textEditingWillEnd(this, condition, _textChanged)) {
  1559.                 return;
  1560.             }
  1561.  
  1562.             didChange = _textChanged;
  1563.             _completeEditing();
  1564.  
  1565.             if (_owner != null) {
  1566.                 _owner.textEditingDidEnd(this, condition, didChange);
  1567.             }
  1568.  
  1569.             if (event.isBackTabKey()) {
  1570.                 sendBacktabCommand();
  1571.                 if( didChange )
  1572.                     sendCommitCommand(true);
  1573.             } else if (event.isTabKey()) {
  1574.                 sendTabCommand();
  1575.                 if( didChange )
  1576.                     sendCommitCommand(true);
  1577.             } else {
  1578.                 sendCommitCommand(true);
  1579.             }
  1580.  
  1581.             return;
  1582.         } else if (event.isLeftArrowKey()) {
  1583.             if( event.isShiftKeyDown() ) {
  1584.               int oldScrollOffset = _scrollOffset;
  1585.               selectRange(_selectionAnchorChar,_selectionEndChar - 1);
  1586.               _computeScrollOffset();
  1587.               if( _scrollOffset != oldScrollOffset ) {
  1588.                   drawInterior();
  1589.               }
  1590.             } else {
  1591.                 oldAnchor = _selectionAnchorChar;
  1592.                 wasASelection = false;
  1593.                 if (_selectionAnchorChar != _selectionEndChar) {
  1594.                     wasASelection = true;
  1595.                     _selectionAnchorChar = selectionStart();
  1596.                     oldAnchor = -1;
  1597.                 } else if (_selectionAnchorChar > 0) {
  1598.                     hideCaret();
  1599.                     _selectionAnchorChar--;
  1600.                 }
  1601.                 _selectionEndChar = _selectionAnchorChar;
  1602.  
  1603.                 if (oldAnchor != _selectionAnchorChar) {
  1604.                     oldOffset = _scrollOffset;
  1605.                     _computeScrollOffset();
  1606.                     if (oldOffset != _scrollOffset || wasASelection) {
  1607.                         _caretShowing = true;
  1608.                         drawInterior();
  1609.                     } else {
  1610.                         showCaret();
  1611.                     }
  1612.                 }
  1613.             }
  1614.             return;
  1615.         } else if (event.isRightArrowKey()) {
  1616.             if( event.isShiftKeyDown() ) {
  1617.               int oldScrollOffset = _scrollOffset;
  1618.               selectRange(_selectionAnchorChar,_selectionEndChar + 1);
  1619.               _computeScrollOffset();
  1620.               if( _scrollOffset != oldScrollOffset ) {
  1621.                   drawInterior();
  1622.               }
  1623.             } else {
  1624.                 oldAnchor = _selectionAnchorChar;
  1625.                 wasASelection = false;
  1626.                 if (_selectionAnchorChar != _selectionEndChar) {
  1627.                   wasASelection = true;
  1628.                   _selectionAnchorChar = selectionStop();
  1629.                   oldAnchor = -1;
  1630.                 } else if (_selectionAnchorChar < _contents.length()) {
  1631.                   hideCaret();
  1632.                   _selectionAnchorChar++;
  1633.                   if (_selectionAnchorChar > _contents.length()) {
  1634.                     _selectionAnchorChar = _contents.length();
  1635.                   }
  1636.                 }
  1637.                 _selectionEndChar = _selectionAnchorChar;
  1638.  
  1639.                 if (oldAnchor != _selectionAnchorChar) {
  1640.                   oldOffset = _scrollOffset;
  1641.                   _computeScrollOffset();
  1642.                   if (oldOffset != _scrollOffset || wasASelection) {
  1643.                     _caretShowing = true;
  1644.                     drawInterior();
  1645.                   } else {
  1646.                     showCaret();
  1647.                   }
  1648.                 }
  1649.             }
  1650.             return;
  1651.         } else if(event.isHomeKey()) {
  1652.             Range r = selectedRange();
  1653.             int oldScrollOffset;
  1654.             if( event.isShiftKeyDown() )
  1655.               selectRange(_selectionAnchorChar,0);
  1656.             else
  1657.               selectRange(new Range(0,0));
  1658.  
  1659.             oldScrollOffset = _scrollOffset;
  1660.             _computeScrollOffset();
  1661.             if( _scrollOffset != oldScrollOffset )
  1662.               drawInterior();
  1663.             return;
  1664.         } else if(event.isEndKey())  {
  1665.             Range r = selectedRange();
  1666.             int oldScrollOffset;
  1667.             int lastIndex = _contents.length();
  1668.  
  1669.             if( event.isShiftKeyDown())
  1670.                 selectRange(_selectionAnchorChar,lastIndex);
  1671.             else
  1672.               selectRange(new Range(lastIndex,0));
  1673.  
  1674.             oldScrollOffset = _scrollOffset;
  1675.             _computeScrollOffset();
  1676.             if( _scrollOffset != oldScrollOffset )
  1677.               drawInterior();
  1678.             return;
  1679.         } else if (!event.isBackspaceKey() &&
  1680.                    !event.isDeleteKey() &&
  1681.                    !event.isPrintableKey()) {
  1682.             return;
  1683.         }
  1684.  
  1685.         if (_oldContents == null) {
  1686.             _oldContents = new FastStringBuffer(_contents.toString());
  1687.         }
  1688.  
  1689.         hideCaret();
  1690.  
  1691.         /* delete the selection */
  1692.         if (_selectionAnchorChar != _selectionEndChar) {
  1693.             contentString = _contents.toString();
  1694.  
  1695.             start = selectionStart();
  1696.  
  1697.             _contents = new FastStringBuffer(
  1698.                                         contentString.substring(0, start));
  1699.             _contents.append(contentString.substring(selectionStop()));
  1700.             _selectionAnchorChar = _selectionEndChar = start;
  1701.  
  1702.             if (event.isBackspaceKey() || event.isDeleteKey()) {
  1703.                 event = null;
  1704.             }
  1705.         }
  1706.  
  1707.         if (event != null) {
  1708.            if (event.isBackspaceKey()) {
  1709.                 if (_contents.length() == 0 || _selectionAnchorChar == 0) {
  1710.                     showCaret();
  1711.                     return;
  1712.                 }
  1713.                 _contents.removeCharAt(_selectionAnchorChar - 1);
  1714.                 _selectionAnchorChar--;
  1715.             } else if(event.isDeleteKey()) {
  1716.                 if(_selectionAnchorChar < _contents.length())
  1717.                   _contents.removeCharAt(_selectionAnchorChar);
  1718.                 else
  1719.                   showCaret();
  1720.             } else {
  1721.                 if(event.isExtendedKeyEvent()) {
  1722.                   _contents.insert(event.keyChar(),_selectionAnchorChar++);
  1723.                 } else {
  1724.                 _contents.insert((char)event.key, _selectionAnchorChar++);
  1725.             }
  1726.             }
  1727.  
  1728.             _selectionEndChar = _selectionAnchorChar;
  1729.         }
  1730.  
  1731.         _computeScrollOffset();
  1732.  
  1733.         drawInterior();
  1734.         showCaret();
  1735.         if (_owner != null) {
  1736.             _owner.textWasModified(this);
  1737.             _textChanged = true;
  1738.         } else if (!_textChanged) {
  1739.             _textChanged = true;
  1740.         }
  1741.     }
  1742.  
  1743.     /** Overridden to process key Events within the TextField. If you want
  1744.       * to process or filter key Events yourself, implement the TextFilter
  1745.       * interface and set yourself as the TextField's filter.
  1746.       * @see #setFilter
  1747.       */
  1748.     public void keyDown(KeyEvent event) {
  1749.         KeyEvent        nextKey;
  1750.  
  1751.         if( !isEditable())
  1752.             return;
  1753.  
  1754.         if(Application.application().handleExtendedKeyEvent() &&
  1755.            JDK11AirLock.hasOneOneEvents()) {
  1756.           if(event.isPrintableKey() && !event.isDeleteKey())
  1757.             return;
  1758.           else if((event.modifiers & KeyEvent.ALT_MASK) == KeyEvent.ALT_MASK)
  1759.             return;
  1760.           else if(event.isBackspaceKey())
  1761.             return;
  1762.         }
  1763.  
  1764.         if (_filter != null) {
  1765.             if (_filter.acceptsEvent(this, event, _keyVector)) {
  1766.                 _keyVector.addElement(event);
  1767.             }
  1768.         } else {
  1769.             _keyVector.addElement(event);
  1770.         }
  1771.  
  1772.         while (!_keyVector.isEmpty()) {
  1773.             nextKey = (KeyEvent)_keyVector.removeFirstElement();
  1774.             _keyDown(nextKey);
  1775.         }
  1776.     }
  1777.  
  1778.     public void keyTyped(KeyEvent event) {
  1779.         KeyEvent        nextKey;
  1780.  
  1781.         if( !isEditable())
  1782.             return;
  1783.  
  1784.         if (_filter != null) {
  1785.             if (_filter.acceptsEvent(this, event, _keyVector)) {
  1786.                 _keyVector.addElement(event);
  1787.             }
  1788.         } else {
  1789.             _keyVector.addElement(event);
  1790.         }
  1791.  
  1792.         while (!_keyVector.isEmpty()) {
  1793.             nextKey = (KeyEvent)_keyVector.removeFirstElement();
  1794.             _keyDown(nextKey);
  1795.         }
  1796.     }
  1797.  
  1798.     /** Override this method to start an editing session if necessary */
  1799.     public void setFocusedView() {
  1800.         if( _editing == false && isEditable() )
  1801.             _startEditing(true); /* Will call setFocusedView with _editing set to true*/
  1802.         else
  1803.             super.setFocusedView();
  1804.     }
  1805.  
  1806.     /* start editing */
  1807.     private void _startEditing(boolean sendMessage) {
  1808.         if (_superview != null) {
  1809.             if( isEditable() )
  1810.                 _canBlink = _caretShowing = hasInsertionPoint();
  1811.             else
  1812.                 _canBlink = _caretShowing = false;
  1813.  
  1814.             _editing = true;
  1815.  
  1816.             if(isSelectable())
  1817.                 this.setFocusedView();
  1818.  
  1819.             if (hasInsertionPoint() && isEditable()) {
  1820.                 showCaret();
  1821.             }
  1822.             if (sendMessage && _owner != null) {
  1823.                 _owner.textEditingDidBegin(this);
  1824.             }
  1825.         }
  1826.     }
  1827.  
  1828.     /* stop all editing, saving changes */
  1829.     private void _completeEditing() {
  1830.         boolean         shouldPerformAction;
  1831.  
  1832.         _oldContents = null;
  1833.  
  1834.         shouldPerformAction = _textChanged;
  1835.  
  1836.         _editing = false;
  1837.  
  1838.         if (_superview != null) {
  1839.             _ignoreWillBecomeSelected = true;
  1840.             _superview.setFocusedView(null);
  1841.             _ignoreWillBecomeSelected = false;
  1842.         }
  1843.  
  1844.         if (shouldPerformAction) {
  1845.             sendContentsChangedCommand();
  1846.         }
  1847.     }
  1848.  
  1849.     void _startBlinkTimer() {
  1850.         if (blinkTimer == null) {
  1851.             blinkTimer = new Timer(this, BLINK_CARET, 750);
  1852.             blinkTimer.start();
  1853.         }
  1854.     }
  1855.  
  1856.     /** Make sure that the selection is defined */
  1857.     void _validateSelection() {
  1858.         String contents = stringValue();
  1859.         Range r;
  1860.  
  1861.         if( _selectionAnchorChar == -1 )
  1862.             selectRange( new Range(0,0));
  1863.         else {
  1864.             if( _selectionAnchorChar < 0 )
  1865.                 _selectionAnchorChar = 0;
  1866.             else if( _selectionAnchorChar > _contents.length())
  1867.                 _selectionAnchorChar = _contents.length();
  1868.  
  1869.             if( _selectionEndChar < 0 )
  1870.                 _selectionEndChar = 0;
  1871.             else if( _selectionEndChar > _contents.length())
  1872.                 _selectionEndChar = _contents.length();
  1873.         }
  1874.     }
  1875.  
  1876.     /** Overridden to notify the TextField it has become the focus of
  1877.       * KeyEvents.
  1878.       */
  1879.     public void startFocus() {
  1880.         _validateSelection();
  1881.         hasFocus = true;
  1882.         if( isEditable())
  1883.             _startBlinkTimer();
  1884.         setDirty(true);
  1885.     }
  1886.  
  1887.     /** Overridden to notify the TextField it has ceased being the focus of
  1888.       * KeyEvents.
  1889.       */
  1890.     public void stopFocus() {
  1891.         if (blinkTimer != null) {
  1892.             blinkTimer.stop();
  1893.             blinkTimer = null;
  1894.         }
  1895.  
  1896.         hasFocus = false;
  1897.         _scrollOffset = 0;
  1898.  
  1899.         /* if editing, we didn't cause the loss of focus */
  1900.         if (_editing && _owner != null && isEditable()) {
  1901.             _owner.textEditingWillEnd(this, TextFieldOwner.LOST_FOCUS,
  1902.                                       _textChanged);
  1903.         }
  1904.  
  1905.         _caretShowing = _canBlink = false;
  1906.  
  1907.         if (_editing && isEditable()) {
  1908.             if (_owner != null) {
  1909.                 _owner.textEditingDidEnd(this, TextFieldOwner.LOST_FOCUS,
  1910.                                          _textChanged);
  1911.             }
  1912.  
  1913.             if (_textChanged) {
  1914.                 sendCommitCommand(false);
  1915.             }
  1916.         }
  1917.         _editing = _textChanged = false;
  1918.  
  1919.         drawInterior();
  1920.     }
  1921.  
  1922.  
  1923.     /** Overridden to notify the TextField that it has ceased being the focus
  1924.       * of KeyEvents, but that it will regain focus when the user clicks on
  1925.       * its InternalWindow.
  1926.       */
  1927.     public void pauseFocus() {
  1928.         if (blinkTimer != null) {
  1929.             blinkTimer.stop();
  1930.             blinkTimer = null;
  1931.             hideCaret();
  1932.         }
  1933.     }
  1934.  
  1935.     /** Overridden to notify the TextField it has become the focus of
  1936.       * KeyEvents, because the user clicked on its InternalWindow.
  1937.       */
  1938.     public void resumeFocus() {
  1939.       if(isEditable())
  1940.         _startBlinkTimer();
  1941.     }
  1942.  
  1943.    /** Causes the TextField to cancel editing by discarding any changes
  1944.      * that the user made.
  1945.      */
  1946.     public void cancelEditing() {
  1947.         if (!isBeingEdited()) {
  1948.             return;
  1949.         }
  1950.  
  1951.         if (_oldContents != null) {
  1952.             _contents = _oldContents;
  1953.             _oldContents = null;
  1954.         }
  1955.  
  1956.         /* cause stopFocus() to get called */
  1957.         _editing = false;
  1958.         if (_superview != null) {
  1959.             _ignoreWillBecomeSelected = true;
  1960.             _superview.setFocusedView(null);
  1961.             _ignoreWillBecomeSelected = false;
  1962.         }
  1963.     }
  1964.  
  1965.     /** Causes the TextField to complete any editing by retaining all
  1966.       * changes the user made to the TextField's text.
  1967.       * @see #cancelEditing
  1968.       */
  1969.     public void completeEditing() {
  1970.         boolean textDidChange = _textChanged;
  1971.  
  1972.         if (!isBeingEdited()) {
  1973.             return;
  1974.         }
  1975.  
  1976.         if (_owner != null &&
  1977.             !_owner.textEditingWillEnd(this, TextFieldOwner.RESIGNED_FOCUS,
  1978.                                        textDidChange)) {
  1979.             return;
  1980.         }
  1981.  
  1982.         _completeEditing();
  1983.  
  1984.         if (_owner != null) {
  1985.             _owner.textEditingDidEnd(this, TextFieldOwner.RESIGNED_FOCUS,
  1986.                                      textDidChange);
  1987.         }
  1988.     }
  1989.  
  1990.  
  1991.  
  1992. /* commands */
  1993.  
  1994.  
  1995.     void sendCommand(String command, Target aTarget) {
  1996.         if (aTarget != null) {
  1997.             /*if (!(aTarget instanceof TextField) ||
  1998.                 !command.equals(SELECT_TEXT) ||
  1999.                 (rootView() != null && rootView().focusedView() == null)) */
  2000.             aTarget.performCommand(command, this);
  2001.         }
  2002.     }
  2003.  
  2004.     void sendTabCommand() {
  2005.         if(_tabCommand != null && _tabTarget != null)
  2006.             sendCommand(_tabCommand, _tabTarget);
  2007.         else if(rootView() != null)
  2008.             rootView().selectViewAfter(this);
  2009.     }
  2010.  
  2011.     void sendBacktabCommand() {
  2012.         if(_backtabCommand != null && _backtabCommand != null)
  2013.             sendCommand(_backtabCommand, _backtabTarget);
  2014.         else if(rootView() != null)
  2015.             rootView().selectViewBefore(this);
  2016.     }
  2017.  
  2018.     void sendContentsChangedCommand() {
  2019.         sendCommand(_contentsChangedCommand, _contentsChangedTarget);
  2020.     }
  2021.  
  2022.     void sendCommitCommand(boolean selectNextField) {
  2023.         if (selectNextField && _commitCommand == null && _commitTarget == null &&
  2024.             _tabCommand != null && _tabTarget != null) {
  2025.             sendTabCommand();
  2026.         }
  2027.         sendCommand(_commitCommand, _commitTarget);
  2028.     }
  2029.  
  2030.     /** Implements the TextField's ExtendedTarget interface */
  2031.     public boolean canPerformCommand(String command) {
  2032.         return (BLINK_CARET.equals(command) ||
  2033.                 SELECT_TEXT.equals(command) ||
  2034.                 (isEditable() && CUT.equals(command)) ||
  2035.                 COPY.equals(command) ||
  2036.                 (isEditable() && PASTE.equals(command)));
  2037.     }
  2038.  
  2039.     /** Implements the TextField's commands:
  2040.       * <ul>
  2041.       * <li>SELECT_TEXT - calls the <b>selectText()</b> method.
  2042.       * </ul>
  2043.       * @see #selectText
  2044.       */
  2045.     public void performCommand(String command, Object data) {
  2046.         if (BLINK_CARET.equals(command)) {
  2047.             blinkCaret();
  2048.         } else if (SELECT_TEXT.equals(command)) {
  2049.             selectText();
  2050.         } else if (CUT.equals(command)) {
  2051.             cut();
  2052.         } else if (COPY.equals(command)) {
  2053.             copy();
  2054.         } else if (PASTE.equals(command)) {
  2055.             paste();
  2056.         } else {
  2057.             throw new NoSuchMethodError("unknown command: " + command);
  2058.         }
  2059.     }
  2060.  
  2061.     private void blinkCaret() {
  2062.         if (_canBlink) {
  2063.             _caretShowing = !_caretShowing;
  2064.             drawCaret();
  2065.         } else if (!_mouseDragging && hasInsertionPoint()) {
  2066.             _canBlink = true;
  2067.         }
  2068.     }
  2069.  
  2070. /* archiving */
  2071.  
  2072.  
  2073.     /** Describes the TextField class' information.
  2074.      * @see Codable#describeClassInfo
  2075.      */
  2076.     public void describeClassInfo(ClassInfo info) {
  2077.         super.describeClassInfo(info);
  2078.  
  2079.         info.addClass("netscape.application.TextField", 3);
  2080.         info.addField(CONTENTS_KEY, STRING_TYPE);
  2081.         info.addField(OWNER_KEY, OBJECT_TYPE);
  2082.         info.addField(FILTER_KEY, OBJECT_TYPE);
  2083.         info.addField(TABREC_KEY, OBJECT_TYPE);
  2084.         info.addField(BACKTABREC_KEY, OBJECT_TYPE);
  2085.         info.addField(CONTENTSCHANGEDREC_KEY, OBJECT_TYPE);
  2086.         info.addField(COMMITREC_KEY, OBJECT_TYPE);
  2087.         info.addField(BORDER_KEY, OBJECT_TYPE);
  2088.         info.addField(FONT_KEY, OBJECT_TYPE);
  2089.         info.addField(TEXTC_KEY, OBJECT_TYPE);
  2090.         info.addField(BACKGROUNDC_KEY, OBJECT_TYPE);
  2091.         info.addField(SELECTIONC_KEY, OBJECT_TYPE);
  2092.         info.addField(CARETC_KEY, OBJECT_TYPE);
  2093.         info.addField(TABCOM_KEY, STRING_TYPE);
  2094.         info.addField(BACKTABCOM_KEY, STRING_TYPE);
  2095.         info.addField(CONTENTSCHANGEDCOM_KEY, STRING_TYPE);
  2096.         info.addField(COMMITCOM_KEY, STRING_TYPE);
  2097.         info.addField(SELECTIONANCH_KEY, INT_TYPE);
  2098.         info.addField(SELECTIONEND_KEY, INT_TYPE);
  2099.         info.addField(JUSTIFICATION_KEY, INT_TYPE);
  2100.         info.addField(SCROLLOFFSET_KEY, INT_TYPE);
  2101.         info.addField(EDITABLE_KEY, BOOLEAN_TYPE);
  2102.         info.addField(SELECTABLE_KEY, BOOLEAN_TYPE);
  2103.         info.addField(SHADOWED_KEY, BOOLEAN_TYPE);
  2104.         info.addField(CANWRAP_KEY, BOOLEAN_TYPE);
  2105.         info.addField(AUTOSCROLLEVENT_KEY, BOOLEAN_TYPE);
  2106.         info.addField(TRANSPARENT_KEY, BOOLEAN_TYPE);
  2107.         info.addField(DRAWABLE_CHAR_KEY,CHAR_TYPE);
  2108.         info.addField(SCROLLABLE_KEY, BOOLEAN_TYPE);
  2109.     }
  2110.  
  2111.     /** Encodes the TextField instance.
  2112.      * @see Codable#decode
  2113.      */
  2114.     public void encode(Encoder encoder) throws CodingException {
  2115.         super.encode(encoder);
  2116.  
  2117.         encoder.encodeString(CONTENTS_KEY, _contents.toString());
  2118.  
  2119.         encoder.encodeObject(OWNER_KEY, (Codable)_owner);
  2120.         encoder.encodeObject(FILTER_KEY, (Codable)_filter);
  2121.  
  2122.         encoder.encodeObject(TABREC_KEY, (Codable)_tabTarget);
  2123.         encoder.encodeObject(BACKTABREC_KEY, (Codable)_backtabTarget);
  2124.         encoder.encodeObject(CONTENTSCHANGEDREC_KEY,
  2125.                                (Codable)_contentsChangedTarget);
  2126.         encoder.encodeObject(COMMITREC_KEY, (Codable)_commitTarget);
  2127.  
  2128.         if (border instanceof EmptyBorder) {
  2129.             encoder.encodeObject(BORDER_KEY, null);
  2130.         } else {
  2131.             encoder.encodeObject(BORDER_KEY, border);
  2132.         }
  2133.  
  2134.         encoder.encodeObject(FONT_KEY, _font);
  2135.  
  2136.         encoder.encodeObject(TEXTC_KEY, _textColor);
  2137.         encoder.encodeObject(BACKGROUNDC_KEY, _backgroundColor);
  2138.         encoder.encodeObject(SELECTIONC_KEY, _selectionColor);
  2139.         encoder.encodeObject(CARETC_KEY, _caretColor);
  2140.  
  2141.         encoder.encodeString(TABCOM_KEY, _tabCommand);
  2142.         encoder.encodeString(BACKTABCOM_KEY, _backtabCommand);
  2143.         encoder.encodeString(CONTENTSCHANGEDCOM_KEY,
  2144.                                _contentsChangedCommand);
  2145.         encoder.encodeString(COMMITCOM_KEY, _commitCommand);
  2146.  
  2147.         encoder.encodeInt(SELECTIONANCH_KEY, _selectionAnchorChar);
  2148.         encoder.encodeInt(SELECTIONEND_KEY, _selectionEndChar);
  2149.         encoder.encodeInt(JUSTIFICATION_KEY, _justification);
  2150.         encoder.encodeInt(SCROLLOFFSET_KEY, _scrollOffset);
  2151.  
  2152.         encoder.encodeBoolean(EDITABLE_KEY, _editable);
  2153.         encoder.encodeBoolean(SELECTABLE_KEY, _selectable);
  2154.         encoder.encodeBoolean(SHADOWED_KEY, _shadowed);
  2155.         encoder.encodeBoolean(CANWRAP_KEY, _canWrap);
  2156.         encoder.encodeBoolean(AUTOSCROLLEVENT_KEY, wantsAutoscrollEvents);
  2157.         encoder.encodeBoolean(TRANSPARENT_KEY, transparent);
  2158.  
  2159.         encoder.encodeChar(DRAWABLE_CHAR_KEY,_drawableCharacter);
  2160.         encoder.encodeBoolean(SCROLLABLE_KEY, isScrollable);
  2161.     }
  2162.  
  2163.     /** Decodes the TextField instance.
  2164.      * @see Codable#decode
  2165.      */
  2166.     public void decode(Decoder decoder) throws CodingException {
  2167.         String          contentString;
  2168.         int version = decoder.versionForClassName("netscape.application.TextField");
  2169.  
  2170.         super.decode(decoder);
  2171.  
  2172.         contentString = decoder.decodeString(CONTENTS_KEY);
  2173.         if (contentString != null) {
  2174.             _contents = new FastStringBuffer(contentString);
  2175.         }
  2176.  
  2177.         _owner = (TextFieldOwner)decoder.decodeObject(OWNER_KEY);
  2178.         _filter = (TextFilter)decoder.decodeObject(FILTER_KEY);
  2179.  
  2180.         _tabTarget = (Target)decoder.decodeObject(TABREC_KEY);
  2181.         _backtabTarget = (Target)decoder.decodeObject(BACKTABREC_KEY);
  2182.         _contentsChangedTarget =
  2183.                     (Target)decoder.decodeObject(CONTENTSCHANGEDREC_KEY);
  2184.         _commitTarget = (Target)decoder.decodeObject(COMMITREC_KEY);
  2185.  
  2186.         setBorder((Border)decoder.decodeObject(BORDER_KEY));
  2187.  
  2188.         _font = (Font)decoder.decodeObject(FONT_KEY);
  2189.  
  2190.         _textColor = (Color)decoder.decodeObject(TEXTC_KEY);
  2191.         _backgroundColor = (Color)decoder.decodeObject(BACKGROUNDC_KEY);
  2192.         _selectionColor = (Color)decoder.decodeObject(SELECTIONC_KEY);
  2193.         _caretColor = (Color)decoder.decodeObject(CARETC_KEY);
  2194.  
  2195.         _tabCommand = decoder.decodeString(TABCOM_KEY);
  2196.         _backtabCommand = decoder.decodeString(BACKTABCOM_KEY);
  2197.         _contentsChangedCommand = decoder.decodeString(CONTENTSCHANGEDCOM_KEY);
  2198.         _commitCommand = decoder.decodeString(COMMITCOM_KEY);
  2199.  
  2200.         _selectionAnchorChar = decoder.decodeInt(SELECTIONANCH_KEY);
  2201.         _selectionEndChar = decoder.decodeInt(SELECTIONEND_KEY);
  2202.         _justification = decoder.decodeInt(JUSTIFICATION_KEY);
  2203.         _scrollOffset = decoder.decodeInt(SCROLLOFFSET_KEY);
  2204.  
  2205.         _editable = decoder.decodeBoolean(EDITABLE_KEY);
  2206.         _selectable = decoder.decodeBoolean(SELECTABLE_KEY);
  2207.         _shadowed = decoder.decodeBoolean(SHADOWED_KEY);
  2208.         _canWrap = decoder.decodeBoolean(CANWRAP_KEY);
  2209.         wantsAutoscrollEvents = decoder.decodeBoolean(AUTOSCROLLEVENT_KEY);
  2210.         transparent = decoder.decodeBoolean(TRANSPARENT_KEY);
  2211.  
  2212.         if( version >= 2 ) {
  2213.             _drawableCharacter = decoder.decodeChar(DRAWABLE_CHAR_KEY);
  2214.         } else
  2215.             _drawableCharacter = ANY_CHARACTER;
  2216.  
  2217.         if( version >= 3 ) {
  2218.             isScrollable = decoder.decodeBoolean(SCROLLABLE_KEY);
  2219.         } else
  2220.             isScrollable = true;
  2221.  
  2222.     }
  2223.  
  2224.     /** Finishes the TextField instance decoding.
  2225.       * @see Codable#finishDecoding
  2226.       */
  2227.     public void finishDecoding() throws CodingException {
  2228.         super.finishDecoding();
  2229.  
  2230.         setFont(_font);
  2231.     }
  2232.  
  2233.     boolean isWordCharacter(char c) {
  2234.         if( c >= '0' && c <= '9' ||
  2235.             c >= 'A' && c <= 'Z' ||
  2236.             c >= 'a' && c <= 'z' )
  2237.             return true;
  2238.         else
  2239.             return false;
  2240.     }
  2241.  
  2242.  
  2243.     Range groupForIndex(int index) {
  2244.         int length = charCount();
  2245.         int relFirstIndex,relLastIndex;
  2246.         int i,l;
  2247.         char c;
  2248.  
  2249.         if( length == 0 )
  2250.             return new Range();
  2251.  
  2252.         if( _drawableCharacter != ANY_CHARACTER )
  2253.             return new Range(0,charCount());
  2254.  
  2255.         if( index < 0 )
  2256.             index = 0;
  2257.         else if( index >= length )
  2258.             index = length-1;
  2259.  
  2260.         i = index;
  2261.         c = _contents.charAt(i);
  2262.  
  2263.         if( c == '\n') {
  2264.             return new Range(i,1);
  2265.         }
  2266.  
  2267.         if( c == ' ' || c == '\t' ) {
  2268.             while(i>0) {
  2269.                 c = _contents.charAt(i);
  2270.                 if( c == ' ' || c == '\t' )
  2271.                     i--;
  2272.                 else
  2273.                     break;
  2274.             }
  2275.             relFirstIndex = i+1;
  2276.  
  2277.             i = index;
  2278.  
  2279.             while(i<length) {
  2280.                 c = _contents.charAt(i);
  2281.                 if( c == ' ' || c == '\t')
  2282.                     i++;
  2283.                 else
  2284.                     break;
  2285.             }
  2286.             relLastIndex = i-1;
  2287.             return new Range(relFirstIndex,relLastIndex - relFirstIndex +1);
  2288.         }
  2289.  
  2290.         if( !isWordCharacter(c) ) {
  2291.             return new Range( index, 1);
  2292.         }
  2293.  
  2294.         relFirstIndex = i;
  2295.         while( relFirstIndex > 0 ) {
  2296.             c = _contents.charAt(relFirstIndex-1);
  2297.             if(!isWordCharacter(c))
  2298.                 break;
  2299.             relFirstIndex--;
  2300.         }
  2301.  
  2302.  
  2303.         relLastIndex = i;
  2304.         while( relLastIndex < (length-1)) {
  2305.             c = _contents.charAt(relLastIndex+1);
  2306.             if(!isWordCharacter(c))
  2307.                 break;
  2308.             relLastIndex++;
  2309.         }
  2310.  
  2311.         return new Range(relFirstIndex, relLastIndex - relFirstIndex + 1);
  2312.     }
  2313.  
  2314.     /** Return the string that should be displayed for a given
  2315.      *  password */
  2316.     private String drawableString() {
  2317.         if( _drawableCharacter == ANY_CHARACTER ) {
  2318.             if(_contents != null)
  2319.                 return _contents.toString();
  2320.             else
  2321.                 return "";
  2322.         }
  2323.  
  2324.         if( _contents != null && _contents.length() > 0 ) {
  2325.             char buf[] = new char[_contents.length()];
  2326.             int i,c;
  2327.  
  2328.             for(i=0,c=buf.length ; i < c ; i++)
  2329.                 buf[i] = _drawableCharacter;
  2330.  
  2331.             return new String(buf);
  2332.         } else
  2333.             return "";
  2334.     }
  2335.  
  2336.     /** Inform the view that it is about to become the selected view
  2337.       *
  2338.       */
  2339.     public void willBecomeSelected() {
  2340.         if(!_ignoreWillBecomeSelected) {
  2341.             selectText();
  2342.         }
  2343.     }
  2344.  
  2345.     /** Return whether this view can become the selected view
  2346.       * when the user is moving from view to views with the keyboard
  2347.       * Returns <b>true</b>
  2348.       *
  2349.       */
  2350.     public boolean canBecomeSelectedView() {
  2351.         if(isEditable())
  2352.             return true;
  2353.         else
  2354.             return false;
  2355.     }
  2356.  
  2357.     /** Return the View that should become selected when the user
  2358.       * press the tab key. If the result is null, the keyboard UI
  2359.       * system will select the next available view.
  2360.       * The default implementation returns the tabField.
  2361.       *
  2362.       */
  2363.     public View nextSelectableView() {
  2364.         if(_tabTarget != null && (_tabTarget instanceof View)) /* Paranoia */
  2365.             return (View)_tabTarget;
  2366.         else
  2367.             return null;
  2368.     }
  2369.  
  2370.     /** Return the View that should become selected when the user
  2371.       * press the backtab key. If the result is null, the keyboard UI
  2372.       * system will select the next available view.
  2373.       * The default implementation return the backtabField.
  2374.       *
  2375.       */
  2376.     public View previousSelectableView() {
  2377.         if(_backtabTarget != null && (_backtabTarget instanceof View)) /* Paranoia */
  2378.             return (View)_backtabTarget;
  2379.         else
  2380.             return null;
  2381.     }
  2382.  
  2383.     /** Copys the current selection.
  2384.       *
  2385.       */
  2386.     public void copy() {
  2387.         Application.setClipboardText(stringForRange(selectedRange()));
  2388.     }
  2389.  
  2390.     /** Cuts the current selection.
  2391.       *
  2392.       */
  2393.     public void cut() {
  2394.         if (isEditable()) {
  2395.             Range range = selectedRange();
  2396.  
  2397.             if(range == null || range.index < 0)
  2398.                 return;
  2399.  
  2400.             Application.setClipboardText(stringForRange(range));
  2401.             replaceRangeWithString(range, "");
  2402.             selectRange(new Range(range.index(), 0));
  2403.         }
  2404.     }
  2405.  
  2406.     /** Replaces the current selection.
  2407.       *
  2408.       */
  2409.     public void paste() {
  2410.         if (isEditable()) {
  2411.             Range range = selectedRange();
  2412.             String text = Application.clipboardText();
  2413.  
  2414.             if(range == null || text == null)
  2415.                 return;
  2416.  
  2417.             replaceRangeWithString(range, text);
  2418.             selectRange(new Range(range.index() + text.length(), 0));
  2419.         }
  2420.     }
  2421.  
  2422.     /** By default TextFields will scroll as the user types, so they can see
  2423.       * what they are typing. This flag indicates if this scrolling should
  2424.       * occur. If <b>isScrollable</b> returns false, the content area that
  2425.       * the user is typing in will not be scrolled. Additionally, if user
  2426.       * drags a selection, the selection will not cause the text to scroll.
  2427.       *
  2428.       */
  2429.     public boolean isScrollable()  {
  2430.         return isScrollable;
  2431.     }
  2432.  
  2433.     /** By default TextFields will scroll as the user types, so they can see
  2434.       * what they are typing. This flag indicates if this scrolling should
  2435.       * occur.
  2436.       *
  2437.       */
  2438.     public void setScrollable(boolean value) {
  2439.         isScrollable = value;
  2440.     }
  2441.  
  2442.     /** Implementation of the FormElement interface
  2443.       *
  2444.       */
  2445.     public String formElementText() {
  2446.         return stringValue();
  2447.     }
  2448.  
  2449. }
  2450.